package ClientLibrary;

import ClientLibrary.Network.NetLayer;
import ClientLibrary.UI.MainForm;
import CommonLibrary.CheckersPosition;
import CommonLibrary.Commnads.*;
import CommonLibrary.Point;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;

public class Board {

	private Position[][] positions;
	private NetLayer layer;
    private MainForm mainForm;
    private int side;
    private int playerId;
    private int gameId;
    private static Board board;
    
    private Position start;
    private Position finish;
    
    public Position getStart()
    {
        return this.start;
    }
    
    public void setStart(int x, int y)
    {
        this.start = this.positions[x][y];
    }
    
    public Position getFinish()
    {
        return this.finish;
    }
    
    public void setFinish(int x, int y)
    {
        this.finish = this.positions[x][y];
    }

    public int getSide(){
        return this.side;
    }
    
    public void setSide(int side){
        this.side = side;
        CheckersPosition.setSide(side);

        this.positions = new Position[8][8];
        for(int y = 0; y < 8; y++)
        {
            for(int x = 0; x < 8; x++)
            {

                Point point = new Point(x, y);
                Checker checker;
                if(CheckersPosition.defaultPositions[x][y] != 0)
                {
                    checker = new Checker(false, true, CheckersPosition.defaultPositions[x][y]);
                }
                else
                {
                    checker = null;
                }
                Position position = new Position(point, checker);
                this.positions[x][y] = position;
            }
        }
    }
    
    public int getPlayerId(){
        return this.playerId;
    }
    
    public int setPlayerId(int id){
        return this.playerId = id;
    }

    public int getGameId(){
        return this.gameId;
    }

    public int setGameId(int id){
        return this.gameId = id;
    }

    public void setLayer(NetLayer layer){
        this.layer = layer;
    }
    
    public NetLayer getLayer(){
        return this.layer;
    }

    private Board(){

    }
    
    public static Board getBoard(){
        if(board == null)
        {
            board = new Board();
        }
        return board;
    }
	
	public Position[][] getPositions() {
		return positions;
	}

	public ArrayList<Position> findMove(int x, int y, boolean fromFirstPosition) {
        
        ArrayList<Position> result = new ArrayList<Position>();

        if(fromFirstPosition)
        {
            this.start = this.positions[x][y];
            if(!this.positions[x][y].getChecker().getDam())
            {
                // Simple checker

                if(y < 8)
                {
                    if(x > 0)
                    {
                        if(this.positions[x - 1][y + 1].getChecker() == null)
                        {
                            result.add(this.positions[x - 1][y + 1]);
                        }
                        else
                        {
                            if(this.isHereEnemy(x - 1, y + 1))
                            {
                                if(y < 7 && x > 1 && this.positions[x - 2][y + 2].getChecker() == null)
                                {
                                    result.add(this.positions[x - 2][y + 2]);
                                    result.addAll(this.findMove(x - 2, y + 2, false));
                                }
                            }
                        }
                    }
                    if(x < 8)
                    {
                        if(this.positions[x + 1][y + 1].getChecker() == null && (x > 1 ? !result.contains(this.positions[x - 2][y + 2]) : true))
                        {
                            result.add(this.positions[x + 1][y + 1]);
                        }
                        else
                        {
                            if(this.isHereEnemy(x + 1, y + 1))
                            {
                                if(y < 7 && x < 7 && this.positions[x + 2][y + 2].getChecker() == null)
                                {
                                    result.add(this.positions[x + 2][y + 2]);
                                    if(x > 0 && y < 8 && result.contains(this.positions[x - 1][y + 1]))
                                    {
                                        result.remove(this.positions[x - 1][y + 1]);
                                    }
                                    result.addAll(this.findMove(x + 2, y + 2, false));
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                // King
                // TODO
            }
        }
        else
        {
            if(y < 7)
            {
                if(x > 1)
                {
                    if(this.isHereEnemy(x - 1, y + 1) && this.positions[x - 2][y + 2].getChecker() == null)
                    {
                        result.add(this.positions[x - 2][y + 2]);
                        result.addAll(this.findMove(x - 2, y + 2, false));
                    }
                }
                if(x < 7)
                {
                    if(this.isHereEnemy(x + 1, y + 1) && this.positions[x + 2][y + 2].getChecker() == null)
                    {
                        result.add(this.positions[x + 2][y + 2]);
                        result.addAll(this.findMove(x + 2, y + 2, false));
                    }
                }
            }
        }
		return result;
	}

    public boolean isHereEnemy(int x, int y)
    {
        if(this.positions[x][y].getChecker() != null)
        {
            if(this.side == 0)
            {
                return this.positions[x][y].getChecker().getType() == 1 ||
                       this.positions[x][y].getChecker().getType() == 3; 
            }
            else if(this.side == 1)
            {
                return this.positions[x][y].getChecker().getType() == 2 ||
                       this.positions[x][y].getChecker().getType() == 4;    
            }
        }
        return false;
    }
    
    public boolean canMoveToThePosition(Position pos){
        return false;
    }

	public void move(ArrayList<Point> step)
    {
        Position start = null;
        Position finish = null;

        for(int y = 0; y < 8; y++)
        {
            for(int x = 0; x < 8; x++)
            {
                if(x == step.get(0).getX() && y == step.get(0).getY())
                {
                    start = this.positions[x][y];
                }
                if(x == step.get(step.size() - 1).getX() && y == step.get(step.size() - 1).getY())
                {
                    finish = this.positions[x][y];
                }
            }
        }

        finish.checker = start.checker;
        start.checker = null;

        this.mainForm.updateCheckers(this.positions);
	}
	
	public boolean register(String login) throws Exception {
		RegisterRequest request = new RegisterRequest();
		request.setLogin(login);
		layer.sendCommand(request);
		Command c = layer.startReceivingCommand();
		
		if (c.getId() == 3) {
			RegisterResponse rRes = (RegisterResponse)c;
			return rRes.getCheckRegister() == 1 ? true : false;
		}
		return false;
	}
	
	public boolean login(String login) throws Exception {
		AuthorizeRequest request = new AuthorizeRequest();
		request.setLogin(login);
		layer.sendCommand(request);
        Command c = layer.startReceivingCommand();
		
		if (c.getId() == 3) {
			AuthorizeResponse aRes = (AuthorizeResponse)c;
			return aRes.getCheckAuthorize() == 1 ? true : false;
		}
		return false;
	}
    
    public void StartGame()
    {
        this.mainForm = new MainForm(this.side);
        this.mainForm.paintFrame();
        this.mainForm.updateCheckers(this.positions);
    }

    public void sendRequest(Command command)
    {
        try
        {
            this.layer.sendCommand(command);
        }
        catch (Exception error)
        {
            System.out.print("Error with send from the board");
        }
    }
}
